#include "ASN_1.inc";
function debug1(strValue)
{
	trace(strValue);
}
function X_509Certificate(data, testPublicKeyLength)
{
	this.boolValid = false;
	this.version = "";
	this.serialNumber = "";
	this.algorithmId = "";
	this.valabilityStart = "";
	this.valabilityEnd = "";
	this.issuer = null;
	this.recipient = null;
	this.intExpireInXDays = 0;
	this.publicKeyFingerprint = "06a00302010202102c48dd930df5598ef93c9954";
	this.shouldtestPublicKeyLength = testPublicKeyLength;
		
	if(data.length < 100)
	{
		trace("Certificate ASN1 input error. Data: " + data.toHexString());
		return;
	}
	
	try
	{
		var asn_cert = new ASN_SEQUENCE(data, "DER");
	}
	catch(error)
	{
		trace("Certificate ASN1 parsing error: " + error + ". Data: " + data.toHexString());
		return;
	}
	
	var i = 0;
	
	try
	{
		//version part may not be here if version = 1 (default value)
		this.version = asn_cert.childs[0].childs[0].childs[i++].childs[0].asInteger().toString();
	}catch(err)
	{
		this.version = "1";
		i = 0;
	}
	
	try
	{
		this.serialNumber = asn_cert.childs[0].childs[0].childs[i++].asHexDump();
		this.algorithmId = asn_cert.childs[0].childs[0].childs[i++].childs[0].asPrintableString();
			
		this.issuer = this.extractByX_500_OID_2_5_4_x(asn_cert.childs[0].childs[0].childs[i++].childs);
		
		this.valabilityStart = asn_cert.childs[0].childs[0].childs[i].childs[0].asPrintableString(); 
		this.valabilityEnd = asn_cert.childs[0].childs[0].childs[i].childs[1].asPrintableString();
			
		var now = new Date();	
		
		this.boolNotValidYet = asn_cert.childs[0].childs[0].childs[i].childs[0].date > now;
		this.boolExpired = asn_cert.childs[0].childs[0].childs[i].childs[1].date < now;
	
		this.intExpireInXDays = 0;
		if(!this.boolExpired)
		{
			this.intExpireInXDays = parseInt((asn_cert.childs[0].childs[0].childs[i].childs[1].date - now)/(1000*60*60*24));
		}
		
		i++;
		
			
		this.recipient = this.extractByX_500_OID_2_5_4_x(asn_cert.childs[0].childs[0].childs[i++].childs);
	}
	catch(error)
	{
		this.boolValid = false;
		trace("Certificate parsing error: " + error + ". ASN: " + asn_cert);
		return;
	}
	
	this.publicKeyFingerprint = "xxx";
	try
	{
		this.publicKey = asn_cert.childs[0].childs[0].childs[i++].childs[1].data;		
		this.publicKeyFingerprint = Plain2MD5(this.publicKey);
		var testPublicKeyLength = this.publicKey.length;
		// blade: test for public key length < 2048
		if (this.shouldtestPublicKeyLength) {
			if (this.publicKey && this.publicKeyFingerprint && testPublicKeyLength <= 141) {
				// prepare public key as a hex string for details
				var hexPublicKey = "";
				for (var a = 1; a < testPublicKeyLength; a = a + 1) {
					var hexCode = this.publicKey.charCodeAt(a).toString(16).toUpperCase();;
					if (hexCode.length == 1)  hexCode = hexCode + "0";
					
    				hexPublicKey = hexPublicKey + '0x'+ hexCode + " ";
    				if (a % 16 == 0) hexPublicKey = hexPublicKey + "\n"; 
				}								
				ReportItem("SSL_Certificate_Public_Key_less_2048.xml", "Public key: [pre]" + hexPublicKey + "[/pre]"); 
			}
		}
	}
	
	catch(error)
	{
		trace("Certificate parsing error (FP): " + error + ". ASN: " + asn_cert);
	}
	
	this.boolValid = true;	
}
X_509Certificate.prototype.extractByX_500_OID_2_5_4_x = function(seqvence)
{
	
	var X_500_OID_2_5_4_x = new Array( 
			"Object Class" ,
		    "Aliased Entry Name",
		    "Knowldge Information",
		    "Common Name",
		    "Surname",
		    "Serial Number",
		    "Country Name",
		    "Locality Name",
		    "State Or Province Name",
		    "Sstreet Address",
		    "Organization Name",
		    "Organizational Unit Name",
		    "Title",
		    "Description",
		    "Search Guide",
		    "Business Category",
		    "Postal Address",
		    "Postal Code",
		    "Post Office Box",
		    "Physical Delivery Office Name",
		    "Telephone Number",
		    "Telex Number",
		    "Teletex Terminal Identifier",
		    "Facsimile Telephone Number",
		    "x121 Address",
		    "International ISDN Number",
		    "Registered Address",
		    "Destination Indicator",
		    "Preferred Delivery Method",
		    "Presentation Address",
		    "Supported Application Context",
		    "Member",
		    "Owner",
		    "Role Occupant",
		    "See Also",
		    "User Password",
		    "User Certificate",
		    "cA Certificate",
		    "Authority Revocation List",
		    "Certificate Revocation List",
		    "Cross Certificate Pair",
		    "Name",
		    "Given Name",
		    "Initials",
		    "Generation Qualifier",
		    "Unique Identifier",
		    "dnQualifier",
		    "Enhanced Search Guide",
		    "Protocol Information",
		    "Distinguished Name",
		    "Unique Member",
		    "House Identifier",
		    "Supported Algorithms",
		    "Delta Revocation List",
			"","","","", //54-57
		    "Attribute Certificate",
		    "","","","","","", //59-64
		    "Pseudonym"); 
	
	
	var retval = new Array();
	for(var i = 0; i < seqvence.length; i++)
	{
		try
		{
			var id = seqvence[i].childs[0].childs[0];
			if(isArray(id.numbers) && (id.numbers.length == 4) && (id.numbers[0] == 2) && (id.numbers[1] == 5) && (id.numbers[2] == 4))
			{
				if (id.numbers[3] < X_500_OID_2_5_4_x.length)
					retval.push(Array(X_500_OID_2_5_4_x[id.numbers[3]],seqvence[i].childs[0].childs[1].asPrintableString()));
				else trace("Unknown X500 OID: " + id.numbers[3]);
			}
			if(id.numbers == "0,9,2342,19200300,100,1,25")//[dc] this is not OID 2.4.4.x
			{
				retval.push(Array("dc",seqvence[i].childs[0].childs[1].asPrintableString()));
			}
		}
		catch(error)
		{
			trace("Error: " + error);
		}
	}
	return(retval);
}
X_509Certificate.prototype.prettyPrint = function()
{
	var retval = "[code][pre]\n";
	retval += "Issuer:\n";
	for(var i = 0; i < this.issuer.length; i++)
		retval += "   " + this.issuer[i][0] + ": " + this.issuer[i][1] + "\n";
	retval += "Recipient: \n";
	for(var i = 0; i < this.recipient.length; i++)
		retval += "   " + this.recipient[i][0] + ": " + this.recipient[i][1] + "\n";
	retval += "\n"
	retval += "Certificate version: " + this.version + "\n";
	retval += "Serial number:       " + this.serialNumber + "\n";
	retval += "Finger print:        " + this.publicKeyFingerprint + "\n";
	retval += "Algorithm ID:        " + this.algorithmId + "\n";
	retval += "Valability start:    " + this.valabilityStart + "\n";
	retval += "Valability end:      " + this.valabilityEnd + "\n";
	retval += "Expire in:           " + this.intExpireInXDays + " days\n";
	retval += "[/pre][/code]";
	return(retval);
}
/* test cases */
/*
x = strFromRawHex("3082061e30820506a00302010202102c48dd930df5598ef93c99547a60ed43300d06092a864886f70d01010505003081ca310b300906035504061302555331173015060355040a130e566572695369676e2c20496e632e311f301d060355040b1316566572695369676e205472757374204e6574776f726b313a3038060355040b1331286329203230303620566572695369676e2c20496e632e202d20466f7220617574686f72697a656420757365206f6e6c79314530430603550403133c566572695369676e20436c6173732033205075626c6963205072696d6172792043657274696669636174696f6e20417574686f72697479202d204735301e170d3036313130383030303030305a170d3136313130373233353935395a3081be310b300906035504061302555331173015060355040a130e566572695369676e2c20496e632e311f301d060355040b1316566572695369676e205472757374204e6574776f726b313b3039060355040b13325465726d73206f66207573652061742068747470733a2f2f7777772e766572697369676e2e636f6d2f727061202863293036313830360603550403132f566572695369676e20436c617373203320457874656e6465642056616c69646174696f6e2053534c2053474320434130820122300d06092a864886f70d01010105000382010f003082010a0282010100bd5688ba88346464cfcdcab0eee71973c572d9bb45bcb5a8ff83be1c03dbed89b72e101a25bc55ca41a19f0bcf195e70b95e394b9e311c5f87ae2aaaa82ba21b3b10235f13b1dd088c4e14da8381e3b58ce368ed2467ce56b6ac9b739644db8a8cb3d6f071938edb71544aeb73596a8f70512c039f97d1cc117abc620d952ac91c7557e9f5c7eaba8435cbc7855a7ee44de111977d0e203445dbf1a209ebeb3d9eb896435e344b08251e431aa2d9b78a01343dc3f8e5af4f8cffcd65f0234ec597b35cda901c82850d060dc122b67b28a403c34c53d158bc72bc0839fca076a8a8e94b6e883de3b331258c7329480e327906ed3d43f4f6e4e9fc7dbe8e08d51f0203010001a382020830820204301d0603551d0e041604144e43c81d76ef37537a4ff2586f94f338e2d5bddf30120603551d130101ff040830060101ff020100303d0603551d200436303430320604551d2000302a302806082b06010505070201161c68747470733a2f2f7777772e766572697369676e2e636f6d2f637073303d0603551d1f043630343032a030a02e862c687474703a2f2f45565365637572652d63726c2e766572697369676e2e636f6d2f706361332d67352e63726c300e0603551d0f0101ff040403020106301106096086480186f8420101040403020106306d06082b0601050507010c0461305fa15da05b3059305730551609696d6167652f6769663021301f300706052b0e03021a04148fe5d31a86ac8d8e6bc3cf806ad448182c7b192e30251623687474703a2f2f6c6f676f2e766572697369676e2e636f6d2f76736c6f676f2e67696630290603551d1104223020a41e301c311a301806035504031311436c617373334341323034382d312d3438301f0603551d230418301680147fd365a7c2ddecbbf03009f34339fa02af333133303d06082b060105050701010431302f302d06082b060105050730018621687474703a2f2f45565365637572652d6f6373702e766572697369676e2e636f6d30340603551d25042d302b06096086480186f8420401060a6086480186f84501080106082b0601050507030106082b06010505070302300d06092a864886f70d010105050003820101002774a634ea1d9de153d61c9d0ca75b4ca967f2f032b7010ffb421838dee4ee49c813c90bec04c340711872764302235dab7bc848141ac87b1dfcf60a9f36a1d20973716696755134bf993051679d54b72645ac73082386269971f48ed7ea399b060923bf62dda8c4b67da489073ef36dae4059507997373d32787db2634bf9ea08690e13ede8cfbbac0586ca22cf88625d3c2249d863d524a6bdef5ce3cc203b22eafc44c6a8e51fe186cd0c4d8f9353d97feea108a7b3309649706ea36c3dd063ef256663ccaab718174eea7076f6ba42a68037094e9f66882e6b3366c8c071a441eb5ae3fc142e4b88fdae6e5b65e927e4bfe4b023c1b27d5b6225d73e10d4");
x = strFromRawHex("3082063b30820523a00302010202102d6d5fd3553a8050cef0d472668d25d3300d06092a864886f70d01010505003081be310b300906035504061302555331173015060355040a130e566572695369676e2c20496e632e311f301d060355040b1316566572695369676e205472757374204e6574776f726b313b3039060355040b13325465726d73206f66207573652061742068747470733a2f2f7777772e766572697369676e2e636f6d2f727061202863293036313830360603550403132f566572695369676e20436c617373203320457874656e6465642056616c69646174696f6e2053534c20534743204341301e170d3039303132393030303030305a170d3130303132393233353935395a3081fb31133011060b2b0601040182373c02010313024742311b3019060355040f131256312e302c20436c6175736520352e2862293111300f060355040513083030383931363836310b30090603550406130247423111300f060355041114084755353120335044311230100603550408130948616d707368697265310e300c06035504071405466c656574312930270603550409142050616c6d657273746f6e20486f7573652c2031313120466c65657420526f616431193017060355040a14104d6f6f7265706179204c696d69746564310b3009060355040b14024954311d301b060355040314147777772e6d6f6f7265706179766965772e636f6d30820122300d06092a864886f70d01010105000382010f003082010a0282010100c37c46e714490a8f885795298077b6095a094dd20d3e4e4d192de37d198b94aec2a8f047e3d657be48f183b36506460814eb593d23225dbb233f539604a8661b7f3f4299544e65d42dc6558d30ba919f7cc6e863e19029e6eb6f6badf75912e4668ad11309c21a8525678a1c0f03f0ae128ff0fc65161621c09b2cfc2416fd1342a0e177d281fcbf8c053586c92c52c4022143dd6907bae55e25281da3336d18082924889c0b29ffcdffe4b1e44d20c96f85c31316d1f30e4a82fdc9e998b403f50378d131e53b8ffc82da42b1537dc436bbb034f77716511938e930f6372941ff2964128de729e890876a8172e5841db2641062d083b3ca1fa5d0131936af430203010001a38201f4308201f030090603551d1304023000301d0603551d0e04160414c25c16b5f5e5371997431a90bb89346f84b3f314300b0603551d0f0404030205a030440603551d20043d303b3039060b6086480186f84501071706302a302806082b06010505070201161c68747470733a2f2f7777772e766572697369676e2e636f6d2f727061303e0603551d1f043730353033a031a02f862d687474703a2f2f4556496e746c2d63726c2e766572697369676e2e636f6d2f4556496e746c323030362e63726c30280603551d250421301f06082b0601050507030106082b0601050507030206096086480186f8420401301f0603551d230418301680144e43c81d76ef37537a4ff2586f94f338e2d5bddf307606082b06010505070101046a3068302b06082b06010505073001861f687474703a2f2f4556496e746c2d6f6373702e766572697369676e2e636f6d303906082b06010505073002862d687474703a2f2f4556496e746c2d6169612e766572697369676e2e636f6d2f4556496e746c323030362e636572306e06082b0601050507010c04623060a15ea05c305a305830561609696d6167652f6769663021301f300706052b0e03021a04144b6bb92896060cbbd052389b29ac4b078b21051830261624687474703a2f2f6c6f676f2e766572697369676e2e636f6d2f76736c6f676f312e676966300d06092a864886f70d01010505000382010100482a456a08fc14ba812d041d0081e00d3fe99c169f9f57eeaf7611cf2dd9899e5a93238d1bcb09187c3df9e3620fe997256c138e37a5ec8b96d2c795753ee5176ce0fe73dfda72abfbbd115630e1948691111d99e09a879975dee3954e316bcae11a8f100edf23e8c6cdc11055d4f6b39128e7665a00d69e4a3699c2a7def9d54d2a712d80651dd1c1383182552aa38c6586c23a82bdb4d175f2447296001b5e73a2f21141d5a2ad19563295301e126ced96c7eabe469146fabe38df87c2e0505d08eb9efde55bff5478aa03e5f74195ffeabb579157e261af3d993468cbac67301a7c17bb3aa9c1eaf63bc18f5b43b44ba1f1a48621b5e5d66cc119a680e031");
x = strFromRawHex("308204e4308203cca00302010202034009ae300d06092a864886f70d01010505003081ca310b30090603550406130255533110300e060355040813074172697a6f6e61311330110603550407130a53636f74747364616c65311a3018060355040a1311476f44616464792e636f6d2c20496e632e31333031060355040b132a687474703a2f2f6365727469666963617465732e676f64616464792e636f6d2f7265706f7369746f72793130302e06035504031327476f204461646479205365637572652043657274696669636174696f6e20417574686f726974793111300f060355040513083037393639323837301e170d3037303530333134303030355a170d3039303631393131303433365a305131153013060355040a130c2a2e7562756e74752e636f6d3121301f060355040b1318446f6d61696e20436f6e74726f6c2056616c696461746564311530130603550403130c2a2e7562756e74752e636f6d30819f300d06092a864886f70d010101050003818d00308189028181009581daf77009b206bf8c54634dc3c9db340cea81ad6db646fc70d4ac07acb7d82be64476afc3bc7ec88267f439e65796613e2919fa48f5fae2ca0d2ce1f8f04b0b82939c0f954f6a6e67997285c315ef5bf900e0cd2950c9482727c5c6e258572640a097471ad7403be88fde988b921086681bc380f067981b0d97480a03efc30203010001a38201cd308201c930090603551d1304023000300b0603551d0f0404030205a0301d0603551d250416301406082b0601050507030106082b0601050507030230560603551d1f044f304d304ba049a0478645687474703a2f2f6365727469666963617465732e676f64616464792e636f6d2f7265706f7369746f72792f676f6461646479657874656e64656469737375696e672e63726c30520603551d20044b30493047060b6086480186fd6d010717013038303606082b06010505070201162a687474703a2f2f6365727469666963617465732e676f64616464792e636f6d2f7265706f7369746f7279307f06082b0601050507010104733071302306082b060105050730018617687474703a2f2f6f6373702e676f64616464792e636f6d304a06082b06010505073002863e687474703a2f2f6365727469666963617465732e676f64616464792e636f6d2f7265706f7369746f72792f67645f696e7465726d6564696174652e637274301d0603551d0e04160414133d894c96ace83809f2ac631ed080bef6c30c20301f0603551d23041830168014fdac6132936c45d6e2ee855f9abae7769968cce730230603551d11041c301a820c2a2e7562756e74752e636f6d820a7562756e74752e636f6d300d06092a864886f70d0101050500038201010093e9c4955133f8319333362b6a2dace8223764df491df9626527b5597fb387028f3c2d018c66cba3e0ef559183be2ffe29ec5d3828ce3f148a46d4742a15c74b1badfeee01115cdab8f701461154b8d036831d821e7a3b562724b21dfbd1ffb695ebc7d03033cd2ce4e287b07346973aff213c3a12e4380b8bfe43f84729b70f114f453db7dc44840591bd5da92a60c864e25b083890b2ecd5ec473dad7688d305f9e0c3777f39487621057d4118f597a8b64693f2a023ba2a2915a15b9a34b43af40b975b75398d237fd543b2c697df299a082df479eab2389812348cb8e966a68d7674273071d4da4ec8af6cf5cf740f42f8d1c78935d9e1e46a6f44e2ebc1");
y = new X_509Certificate(x);
traceObject(y);
*/
